package com.googlecode.tracey.ui;

import com.googlecode.totallylazy.Callable1;
import com.googlecode.totallylazy.Maps;
import com.googlecode.tracey.ui.config.JsonConfigModule;
import com.googlecode.tracey.ui.demo.DemoModule;
import com.googlecode.utterlyidle.ServerConfiguration;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.googlecode.funclate.json.Json.parse;
import static com.googlecode.totallylazy.Bytes.bytes;
import static com.googlecode.totallylazy.Closeables.using;
import static com.googlecode.totallylazy.Files.write;
import static com.googlecode.totallylazy.Maps.get;
import static com.googlecode.tracey.ui.config.JsonConfigModule.getJson;
import static com.googlecode.utterlyidle.ApplicationBuilder.application;
import static com.googlecode.utterlyidle.ServerConfiguration.defaultConfiguration;
import static java.lang.Integer.parseInt;
import static java.util.Collections.EMPTY_MAP;

public class Main {

    public static void main(String[] args) throws IOException {
        final URL configUrl = configFileUrl(args);
        if(configUrl == null) {
            System.err.println("specify url to config file");
            System.exit(1);
        }
        System.out.println("Running with configuration '" + configUrl + "'");
        final Map<String,Object> configJson = parse(getJson(configUrl));
        Map<String,Object> options = (Map<String, Object>) get(configJson, "options").getOrElse(EMPTY_MAP);
        ServerConfiguration config = defaultConfiguration().port(parseInt(get(options, "port").getOrElse("9000").toString()));
        application(new WebApplication(config.basePath(), new JsonConfigModule(configJson))).start(config);
    }

    private static URL configFileUrl(String[] args) throws MalformedURLException {
        if (args.length == 0 && !new File("config.json").exists()) {
            System.out.println("Creating default configuration in './config.json'");
            return createDefaultConfig().toURI().toURL();
        } else if (args.length == 1) {
            if(new File(args[0]).exists()) {
                return new File(args[0]).toURI().toURL();
            }
            return new URL(args[0]);
        }
        return null;
    }

    private static File createDefaultConfig() {
        return using(DemoModule.class.getResourceAsStream("demo-config.json"), new Callable1<InputStream, File>() {
            @Override
            public File call(InputStream inputStream) throws Exception {
                return write(bytes(inputStream), new File("config.json"));
            }
        });
    }
}
